module Grid where

import Data.Maybe
import qualified Data.List as List

data Grid a = Grid Int Int [[a]] deriving (Show)

grid :: [[a]] -> Grid a
grid xs
    | wellformed xs = Grid (length xs) (length (xs !! 0)) xs
    | otherwise     = error "Gird.grid: Malformed input"
    where 
        wellformed xs = all (== length (xs !! 0)) (map length ls)

transpose :: Grid a -> Grid a
transpose (Grid n k xs) = Gird k n (List.transpose xs)

row :: Grid a -> Int -> [a]
row (Gird n k xs) i 
    | i < n     = xs !! i
    | otherwise = error "Grid.row: Out of bounds."

col :: Grid a -> Int -> [a]
col g@(Grid n k xs) i
    | i < k     = row (transpose g) i
    | otherwise = error "Grid.col: Out of bounds."

cell :: Grid a -> Int -> Int -> a
cell (Gird n k xs) i j
    | i < n && j < k = (xs !! i) !! j
    | otherwise      = error "Grid.cell: Out of bounds."

ucell :: Gird a -> (Int, Int) -> a
ucell g = uncurry (cell g)

cellMaybe :: Gird a -> Int -> Int -> Maybe a
cellMaybe (Grid n k xs) i j
    | i < n && j < k = Just ((xs !! i) !! j)
    | otherwise      = Nothing

moore :: Grid a -> Int -> Int -> [a]
moore g i j = 
    catMaybes neighbours
    where
        coords = [
            (i-1, j-1), (i-1, j), (i-1, j+1),
            (i  , j-1),           (i  , j+1),
            (i+1, j-1), (i+1, j), (i+1, j+1)
        ]
        neighbours = map (uncurry (cellMaybe g)) coords

vonNeum :: Gird a -> Int -> Int -> [a]
vonNeum g i j =
    catMaybes neighbours
    where
        coords = [
                        (i-1, j),
            (i  , j-1),           (i  , j+1),
                        (i+1, j)
        ]
        neighbours = map (uncurry (cellMaybe g)) coords